(load "~/quicklisp/setup.lisp")

(ql:quickload '(cl-who parenscript css-lite cl-json usocket hunchentoot ))

(in-package :cl-user)

(defpackage :field
 (:use :cl :cl-who :parenscript )
 (:import-from :css-lite :css)
 (:import-from :json :encode-json-to-string))


(defpackage :main
 (:use :cl :cl-who :hunchentoot :parenscript)
 (:import-from :css-lite :css)
 (:import-from :json :encode-json-to-string))
 (in-package :main)

 (defvar *fields* '())

 (defclass properties ()
   ((name  :accessor name :initarg :name)
    (display-name :accessor display-name :initarg :display-name)
    (order :accessor order :initarg :order)
    (hint :accessor hint :initarg :hint :initform "")
    (style :accessor style :initform ())))

(defclass textbox (properties) () 
)
(defmethod label (properties)
  (format nil "<span class='field-label'>~A</span>" (slot-value properties 'display-name))
)
(defgeneric representation (properties))

(defmethod representation (textbox)
  (format nil "<input type='text' id='~A' />" (slot-value textbox 'name)))


;; Encapsulate the back end.
(defun get-instance-by-value (name)
 (find name *fields* :test #'string-equal
                    :key #'name))

(defun field-from-name (name)
  (get-instance-by-value name))

(defun field-stored? (field-name)
  (field-from-name field-name))

(defun fields ()
 (sort (copy-list *fields*) #'< :key #'order))

(defun add-field (this-object)
 (unless (field-stored? (name this-object))
   (push this-object *fields*)))

(setf *catch-errors-p* nil)

;;add fields
(add-field (make-instance  'textbox :name "a-field" :order 1 :display-name "First Field"))
(add-field (make-instance  'textbox :name "b-field" :order 100 :display-name "Last Field"))
(add-field (make-instance  'textbox :name "c-field" :order 50 :display-name "Middle Field" :hint "Fill this out first"))


;; Automatically creates a Hunchentoot handler for the given URL (plus .htm) associating
;; it with a function of the same name.
(defmacro define-url-fn ((name) &body body)
  `(progn
     (defun ,name ()
       ,@body)
     (push (create-prefix-dispatcher ,(format nil "/~(~a~)" name) ',name) *dispatch-table*)))

;; All pages on the Retro Games site will use the following macro; less to type and 
;; a uniform look of the pages (defines the header and the stylesheet).
(defmacro standard-page ((&key title) &body body)
  `(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
     (:html :xmlns "http://www.w3.org/1999/xhtml"  :xml\:lang "en" :lang "en"
       (:head 
         (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8")
	  (:title ,title)
	   (:link :type "text/css" :rel "stylesheet" :href "/style.css")
           (:script :type "text/javascript" :src "/script/jquery.js")    
           (:script :type "text/javascript" :src "/script/validation.js")
           (:script :type "text/javascript" :src "/script/jqueryvalidate.js")
          (:body 
	        (:div :id "error" :style "display:none" ; Start all pages with our header.aa
		  (:p "Please correct the following items"))
		(:div :id "content"
		     ,@body))))))

;; The functions responsible for generating the HTML go here.
;;

(define-easy-handler (tutorial2-javascript :uri "/validation.js") ()
  (setf (content-type*) "text/javascript")
    (ps ((@ ($ ) ready)
      (lambda ()
;        (chain ($ "#form1") (validate (create rules "")))

        (let ((container ($ "#error"))))
        (chain ($ "#form1") (validate (create errorcontainer ($ "#error"))))
        (let ((validator (chain ($ "#form1") (validate (create errorcontainer container wrapper "li" meta "validate" errorlabelcontainer ($ "ol" container)))))))
        (let ((isvalid (chain validator (valid)))))
        isvalid ))))

(define-url-fn (default)
  (standard-page (:title "Top Retro Games")
     (:h1 "Vote on your all time favourite retro games!")
     (:p "Missing a game? Make it available for votes " (:a :href "new-game.htm" "here"))
     (:h2 "Current stand")
     (:p
       (dolist (field (fields))	
         (htm
          (:p
           (fmt "~A ~A - ~d ~A ~A" (label field) (name field) (order field) (representation field) (hint field))))))))


(define-url-fn (new-game)
  (standard-page (:title "Add a new game")
     (:h1 "Fill out the form")
     (:form :id "form1" 
         (dolist (field (fields))
           (htm
            (:p
              (:span '(label field))
              (:input :type "text" :id (name field) :name (name field) :class "txt" :maxvalue "1" :class "required"))))
       (:p (:input :type "submit" :value "Add" :class "btn")))))
;;start the webserver
(defvar *web-server* '())
(setf *web-server* (make-instance 'hunchentoot:acceptor :port 9090))
(hunchentoot:start *web-server*)

;; Publish all static content.
(push (create-static-file-dispatcher-and-handler "/logo.jpg" "imgs/Commodore64.jpg") *dispatch-table*)
(push (create-static-file-dispatcher-and-handler "/style.css" "css/style.css") *dispatch-table*)
(push (create-static-file-dispatcher-and-handler "/jquery.js" "thirdparty/jquery.js") *dispatch-table*)
(push (create-static-file-dispatcher-and-handler "/jqueryvalidate.js" "thirdparty/jquery.validate.js") *dispatch-table*)
